<?php

/*	Social.twitter OBJECT
 *  
 *  @author: oneDot only .
 *  @date: 2010-06-11
 *
 */

// communicate with external twitter class (praise Tijs Verkoyen)
// check out documentation on http://classes.verkoyen.eu/twitter_oauth/docs
require_once ROOT . 'engine/ext/twitter/twitter.php';


// setup module class 
class SocialTwitter extends MOD {


	/**
	 * Define Twitter default url 
	 *
	 * @name url	Twitter url 
	 */
	const url	= "http://twitter.com/";


	function __construct( $vars ) {

		$this->_addvars( $vars );
		$this->_ref();
	}
	
	// output function
	public function output() { 


		if( $this->action ) $result = $this->{ "filter_" . $this->action }();
		
		$this->addclass( $this->action );
		
		if ( is_array( $result ))
			 $result = "<ul>" . implode( "\n", $result ) . "</ul>";
	
		return $this->parse( $result ) . $this->render_js();
	
	}

	
	// connect with twitter
	private function twitter_connect() {
		global $DB;
	

		// setup connection with callback url
		$twitter = new Tweet(json_decode($DB->get_key("social.twitter", "active", "meta"))->api, json_decode($DB->get_key("social.twitter", "active", "meta"))->secret);
		
		// authorize
		$twitter->setOAuthToken(json_decode($DB->get_key("social.twitter", "active", "meta"))->oauth_token);
		$twitter->setOAuthTokenSecret(json_decode($DB->get_key("social.twitter", "active", "meta"))->oauth_token_secret);
				
		return $twitter;

	}
	
	// try timeline
	private function twitter_getTimeline( $user, $limit ) {
		global $Twitter;
		
		try {
			
			return $Twitter->statusesUserTimeline(null, null, $user, null, null, $limit, null, null );
		
		} catch (Exception $e) {
		
			// Dit zou kunnen:
			// echo 'Caught exception: ',  $e->getMessage(), "\n";
			// maar we doen het effe pragmatisch:
			return array();
		}
		
	}
	
	
	private function filter_hashtag() {
		
		if( $json = @file_get_contents( 'http://search.twitter.com/search.json?rpp=100&q=%23' . $this->vars->hashtag )) {
		
			$result = json_decode( $json )->results;
			//$result->text = str_replace( '#' . strtolower( $this->vars->hashtag ), '', strtolower( utf8_decode( $node->text )));
			return $this->print_other_tweets( $result, 'item', $this->vars->limit );
		
		}
	
	}
	
	
	// show timeline (from authenticated user & friends)
	private function filter_home_timeline() {
	
		// connect to twitter
		$twitter = $this->twitter_connect();
		
		// print time_line
		$response = $twitter->statusesHomeTimeline(null, null, $this->vars->limit, null, null);
		return $this->print_other_tweets($response);
		
	}
	
	
	
	// show timeline (from authenticated user)
	private function filter_user_timeline() {
		global $Object, $Twitter;
		
		if( !is_array(  		$users	= $this->vars->screenname ) && $users )
								$users	= array( $this->vars->screenname );
		else if( $Object && (	$user	= $Object->get( "twitter" )))
								$users	= array( $user );

		$CACHE = new CACHE( 30, 10 );
		
		
		if( $users )
			foreach( $users as $user ) {
			
				$tweets = $CACHE->test( $this->vars->type, 0, array( "screenname"=> $user ), $this->vars->limit, true );
				
				if( count( $tweets ) == $this->vars->limit )
					foreach( $tweets as $t )
				 	
				 		$response[] = (array) $t;
				else	$refresh[] = $user;
				
			}

		
		if( $refresh ) {
			
			$Twitter		= $this->twitter_connect();
			$Twitter_status	= $Twitter->accountRateLimitStatus();
			
			foreach (		$refresh as $user )
				if((( int )	$Twitter_status[ "remaining_hits" ] &&
					// Try loading tweets, else filter old tweets
					count( $tweets = $this->twitter_getTimeline( $user, $this->vars->limit )))
				||	count( $tweets = $CACHE->filter( $this->vars->type, 0, array( "screenname"=> $user ), $this->vars->limit, true )))
					
					foreach( $tweets as $t ) {
						
						unset( $t[ "source" ], $t[ "profile_sidebar_border_color" ], $t[ "profile_background_image_url" ] );
						$t[ "text" ] = str_replace( "\n", " ", $t[ "text" ]);
					
						$CACHE->insert( $this->vars->type, $t, 0, $t[ "id" ], array( "screenname"=> $user ));
						
						$response[] = $t;
					}

		}			
			 
		if( $response )	
			$response	= $this->sortByInteger( $response, 'id' );
		
		return $this->print_tweets($response);

	}
	
	private function filter_user_timeline_deprecated() {
		global $Object, $Twitter;
		
		if( !is_array(  		$users	= $this->vars->screenname ) && $users )
								$users	= array( $this->vars->screenname );
		else if( $Object && (	$user	= $Object->get( "twitter" )))
								$users	= array( $user );

		$CACHE = new CACHE( 30, 10 );
		
		if( $users )
			foreach( $users as $user ) {
			
				$tweets = $CACHE->test( $this->vars->type, 0, array( "screenname"=> $user ), $this->vars->limit, true );
				
				if( count( $tweets ) == $this->vars->limit )
					foreach( $tweets as $t )
				 	
				 		$response[] = (array) $t;
				else	$refresh[] = $user;
				
			}

		
		if( $refresh ) {
			
			$Twitter = $this->twitter_connect();
			
			foreach ( $refresh as $user )
				if(
					// Try loading tweets, else filter old tweets
					count( $tweets = $this->twitter_getTimeline( $user, $this->vars->limit ))
				||	count( $tweets = $CACHE->filter( $this->vars->type, 0, array( "screenname"=> $user ), $this->vars->limit, true )))
					foreach( $tweets as $t ) {
						
						unset( $t[ "source" ], $t[ "profile_sidebar_border_color" ], $t[ "profile_background_image_url" ] );
						$t[ "text" ] = str_replace( "\n", " ", $t[ "text" ]);
					
						$CACHE->insert( $this->vars->type, $t, 0, $t[ "id" ], array( "screenname"=> $user ));
						
						$response[] = $t;
					}

		}			
			 
		if( $response )	
			$response	= $this->sortByInteger( $response, 'id' );
		
		return $this->print_tweets($response);

	}


	
	
	/////////// DEPRECATED!!!!
	// show timeline (from authenticated user)
	private function filter_user_timeline_old() {
	
		// connect to twitter
		$twitter = $this->twitter_connect();
		
		// print time_line
		if (empty($this->vars->screenname))
			$response 	= $twitter->statusesUserTimeline(null, null, null, null, null, $this->vars->limit, null, null);
			
		else 
			if ( is_array( $this->vars->screenname )) {
				$response = array();
				foreach ( $this->vars->screenname as $tweeter ){
					$tweets 	= $twitter->statusesUserTimeline(null, null, $tweeter, null, null, $this->vars->limit, null, null );
					$response 	= array_merge( $response, $tweets );
				}
				$response	= $this->sortByInteger( $response, 'id' );
			} else {
				$response 	= $twitter->statusesUserTimeline(null, null, $this->vars->screenname, null, null, $this->vars->limit, null, null);
			}
			
			
		return $this->print_tweets($response);
		
	}
	
	
	// show mentions for authenticated user
	private function filter_mentions() {
	
		// connect to twitter
		$twitter = $this->twitter_connect();
		
		// print mentions
		$response = $twitter->statusesMentions(null, null, $this->vars->limit, null);
		return $this->print_tweets($response);
		
	}
	
	
	// update status 
	private function filter_link( $response = false ) {
		
		// connect to twitter
		$twitter = $this->twitter_connect();
		
		// get account & link
		if( $response )
			$response[] = $response;
		
		else if (empty($this->vars->screenname))
			$response 	= $twitter->statusesUserTimeline(null, null, null, null, null, 1, null, null);
			
		else 
			$response 	= $twitter->statusesUserTimeline(null, null, $this->vars->screenname, null, null, 1, null, null);
			
		
		$url 		=  $this->render_url();
		
		
		// output link
		$link[]		= '<a target="_blank" href="' . $url . '" class="twitter_link">' . $this->unshift_content() . '</a>';
		return $link;
	}
	
	
	// update status 
	private function filter_update() {
	
		// connect to twitter
		$twitter = $this->twitter_connect();
		
		// update status
		$twitter->statusesUpdate( $this->vars->message );
	}
	
	
	
	// print functions 
	function print_tweets( $nodes, $class = 'item' ) {
	
		if( $nodes )
			foreach ($nodes as $node) {
			
				// filter text
				$text = $node['text'];
				$text = preg_replace("/([\w]+:\/\/[\w-?&;#~=\.\/\@]+[\w\/])/e","'<a target=\"_blank\" href=\"\\1\">'.substr('\\1',7).'</a>'", $text );
			
				if( $this->vars->showname )				
					$text .= "<a target='_blank' class='user' href='" . $this->render_url( "user", $node ) . "'>{$node['user']['name']} - " .$this->render_date( $node[ 'created_at' ]). "</a>";

				$res[] = '<li class="' . $class . '">' . $text . '</li>';
			
			}

		return ( $res )? $res : "no tweets.<br />";
	}

	// print functions 
	function print_other_tweets( $nodes, $class = 'item', $limit = false ) {
	
		$i = 0;
	
		$res[] = '<ul>';
		foreach ($nodes as $node) {
			
			$node = (( is_object( $node )) ? (array) $node : $node );
			if( $node['from_user'] )
				$node['user']['screen_name'] = $node['from_user'];
			
			// filter text
			$text = utf8_decode($node['text']);
			$text = preg_replace("/([\w]+:\/\/[\w-?&;#~=\.\/\@]+[\w\/])/i","<a target=\"_blank\" href=\"$1\">$1</A>",$text);
						
			$res[] = '<li class="' . $class . '"><span class="user">' . $node['user']['screen_name'] . '</span> ' . $text . '</li>';
			
			$i++;
			if( $limit && $limit <= $i )
				break;
		}
		$res[] = '</ul>';
		return $res;
	}
	
	
	private function render_url( $type = "user", $tweet = false ) {
	
		if( !$tweet ) {
			// connect to twitter
			$twitter = $this->twitter_connect();
		
			// get account & link
			$tweet 	= array_shift( 
							$twitter->statusesUserTimeline( null, null, empty($this->vars->screenname)? null : $this->vars->screenname, null, null, 1, null, null)
						);
		}		
		
		switch( $type ) {
			case "user" : return self::url . "#!/" . $tweet['user']['screen_name'];
		}

	}
	
	
	private function render_date( $datestr ) {
		
		$diff = time() - strtotime( $datestr);
		
		if ( 		$diff < 3600 )
			 $time = ( $cur = round( $diff /60 )) . " minute";
		
		else if (	$diff < 86400 )
			 $time = ( $cur = round( $diff /3600 )) . " hour";
			
		else if (	$diff < 432000 )
			 $time = ( $cur = round( $diff /86400 )) . " day";
			
		else $time = "some time";
		
		
		return $time . (( !$cur || $cur == 1 )? "": "s" ) . " ago";
	}

	
	
	/**
	 * Search twitter 
	 *
	 * Small method that returns array with values/objects
	 * A simple foreach makes it possible to output anything you want (lists)
	 *
	 * possible values for $what
	 * {[profile_image_url, created_at, from_user, metadata{[result_type]}, to_user_id, text, id, from_user_id, geo, iso_language_code, source]}
	 *
	 * @param		$tag (string)
	 * @param		$what (string vs array)
	 * @return		array (with values vs objects)
	 */
	 
	function search_twitter( $tag, $what = 'text' ) {
	
		// define url and get posts
		$twitterSearch = json_decode( file_get_contents('http://search.twitter.com/search.json?q=' . $tag ))->results;
		
		// check if there is any result	
		if ( !empty($twitterSearch[0])) {
			
			// counter
			$i = 0;
			foreach ( $twitterSearch as $post ) {
				
				// !is_array - return array with values
				if (!is_array( $what )) 
					$return[$i] = $post->$what;
					
				// is array - return array with objects
				else if ( is_array( $what )) {
					foreach($what as $w)
						$return[$i]->$w = $post->$w;
				}
				$i++;
			}
		
		} else {
			$return = 'empty';
		}
				
		return $return;
	}	
	
	
	function sortByInteger( $array, $field ) {
      	$sort = "return -strnatcmp(\$p1['$field'], \$p2['$field']);";
       	usort($array, create_function('$p1,$p2', $sort));
        
        return $array;
    }



}
